package com.hydra.framework.event.core.helper;

import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.hydra.framework.event.core.EventDispatcher.EVENT_LOG_TAG;

/**
 * 辅助类，遍历获取当前类和父类的绑定的(过滤了系统父类)函数和field信息
 */
public class EventHelper {

    private static final String ANDROID_SYSTEM_PACKAGE_PREFIX = "android.";
    private static final String JAVA_SYSTEM_PACKAGE_PREFIX = "java.";
    private static final String JAVAX_SYSTEM_PACKAGE_PREFIX = "javax.";

    public static List<Method> getExcludeSystemMethods(Class<?> clazz) {
        //这里的异常处理和Android系统的类混淆有关系
        try {
            return getMethodRecursive(new ArrayList<>(), clazz);
        } catch (NoClassDefFoundError error) {
            Log.e(EVENT_LOG_TAG, "getExcludeSystemMethods error clazz : "
                    + clazz.getName() + " exception : " + error.toString());

            return Arrays.asList(clazz.getMethods());
        }
    }

    private static List<Method> getMethodRecursive(List<Method> methodList, Class<?> clazz) {
        if (clazz == null) {
            return methodList;
        }

        String name = clazz.getName();

        if (name.startsWith(ANDROID_SYSTEM_PACKAGE_PREFIX) ||
                name.startsWith(JAVA_SYSTEM_PACKAGE_PREFIX) ||
                name.startsWith(JAVAX_SYSTEM_PACKAGE_PREFIX)) {
            return methodList;
        }

        methodList.addAll(Arrays.asList(clazz.getDeclaredMethods()));

        return getMethodRecursive(methodList, clazz.getSuperclass());
    }

    //和method处理方法类似，不过对于数据存储类来说，一般不太会继承太多，field总体不会太耗时
    public static List<Field> getExcludeSystemFields(Class<?> clazz) {
        //这里的异常处理和Android系统的类混淆有关系
        try {
            return getFieldRecursive(new ArrayList<>(), clazz);
        } catch (NoClassDefFoundError error) {
            Log.e(EVENT_LOG_TAG, "getExcludeSystemFields error clazz : "
                    + clazz.getName() + " exception : " + error.toString());

            return Arrays.asList(clazz.getFields());
        }
    }

    private static List<Field> getFieldRecursive(List<Field> fieldList, Class<?> clazz) {
        if (clazz == null) {
            return fieldList;
        }

        String name = clazz.getName();

        if (name.startsWith(ANDROID_SYSTEM_PACKAGE_PREFIX) ||
                name.startsWith(JAVA_SYSTEM_PACKAGE_PREFIX) ||
                name.startsWith(JAVAX_SYSTEM_PACKAGE_PREFIX)) {
            return fieldList;
        }

        fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));

        return getFieldRecursive(fieldList, clazz.getSuperclass());
    }
}
